#pragma once

#include <string>
#include <memory>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <mysql_driver.h>
#include <mysql_connection.h>
#include <cppconn/statement.h>
#include <cppconn/prepared_statement.h>
#include <cppconn/resultset.h>

namespace cpp_backend
{
    namespace database
    {

        /**
         * @brief MySQL连接包装类
         */
        class MySQLConnection
        {
        public:
            explicit MySQLConnection(sql::Connection *conn) : conn_(conn) {}

            ~MySQLConnection()
            {
                if (conn_)
                {
                    delete conn_;
                }
            }

            sql::Connection *Get() { return conn_; }

            bool IsValid()
            {
                return conn_ && !conn_->isClosed();
            }

        private:
            sql::Connection *conn_;
        };

        using MySQLConnectionPtr = std::shared_ptr<MySQLConnection>;

        /**
         * @brief MySQL连接池(单例模式)
         *
         * 管理MySQL连接,提供连接复用,避免频繁创建/销毁连接
         */
        class MySQLPool
        {
        public:
            /**
             * @brief 获取单例实例
             */
            static MySQLPool &Instance();

            /**
             * @brief 初始化连接池
             *
             * @param host 主机地址
             * @param port 端口
             * @param database 数据库名
             * @param username 用户名
             * @param password 密码
             * @param pool_size 连接池大小
             * @return 是否初始化成功
             */
            bool Initialize(const std::string &host, int port,
                            const std::string &database,
                            const std::string &username,
                            const std::string &password,
                            int pool_size = 10);

            /**
             * @brief 获取连接
             *
             * @param timeout_ms 超时时间(毫秒),0表示无限等待
             * @return 连接对象,失败返回nullptr
             */
            MySQLConnectionPtr GetConnection(int timeout_ms = 5000);

            /**
             * @brief 归还连接
             *
             * @param conn 连接对象
             */
            void ReturnConnection(MySQLConnectionPtr conn);

            /**
             * @brief 获取连接池统计信息
             */
            struct PoolStats
            {
                int total_connections;
                int available_connections;
                int active_connections;
            };

            PoolStats GetStats() const;

            /**
             * @brief 关闭连接池
             */
            void Shutdown();

        private:
            MySQLPool() = default;
            ~MySQLPool();
            MySQLPool(const MySQLPool &) = delete;
            MySQLPool &operator=(const MySQLPool &) = delete;

            /**
             * @brief 创建新连接
             */
            sql::Connection *CreateConnection();

            std::string host_;
            int port_;
            std::string database_;
            std::string username_;
            std::string password_;
            int pool_size_;

            sql::mysql::MySQL_Driver *driver_;
            std::queue<MySQLConnectionPtr> available_connections_;
            mutable std::mutex mutex_;
            std::condition_variable cv_;
            bool shutdown_;
        };

        /**
         * @brief RAII风格的连接管理器
         *
         * 自动获取和归还连接
         */
        class MySQLConnectionGuard
        {
        public:
            explicit MySQLConnectionGuard(int timeout_ms = 5000)
                : conn_(MySQLPool::Instance().GetConnection(timeout_ms)) {}

            ~MySQLConnectionGuard()
            {
                if (conn_)
                {
                    MySQLPool::Instance().ReturnConnection(conn_);
                }
            }

            sql::Connection *operator->()
            {
                return conn_ ? conn_->Get() : nullptr;
            }

            sql::Connection *Get()
            {
                return conn_ ? conn_->Get() : nullptr;
            }

            bool IsValid() const
            {
                return conn_ && conn_->IsValid();
            }

        private:
            MySQLConnectionPtr conn_;
        };

    } // namespace database
} // namespace file_server
